/*********************************************************************************
 *      Copyright:  (C) 2022 Zhukaifa（928085237@qq.com）
 *                  All rights reserved.
 *
 *       Filename:  route_opt.c 
 *
 *    Description:  Operate the network route
 *                 
 *        Version:  1.0.0(28/07/22)
 *         Author:  Zhukaifa（928085237@qq.com）
 *      ChangeLog:  1, Release initial version on "28/07/22 21:52:04"
 *                 
 ********************************************************************************/


#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <unistd.h>

#include <logger.h>

 
/*********************************************************************************
 *
 *           Name:       route_ping 
 *
 *    Description:       get the packet loss rate by ping
 *                 
 *        Input args:     
 *                       iface_name:   interface name
 *                               pc:   ping pc
 *
 *       Output args: 
 *
 *      return value:
 *                       <0 failure
 *                       =0 success
 *
 *                 
 ********************************************************************************/



int route_ping(char *iface_name, char *pc)
{

	char    buf[32];
	char    f_buf[1024];
	char    r_buf[16];
	FILE   *fp;
	char   *ptr=NULL;
	char   *tok=NULL;
	char    tok_buf[4];
	char    rate_buf[4];
	int     rate=-1;

	memset(buf, 0, sizeof(buf));
	memset(r_buf, 0, sizeof(r_buf));
	memset(f_buf, 0, sizeof(f_buf));
	snprintf(buf, sizeof(buf), "ping %s -I %s -c 4", pc, iface_name);

	if(!iface_name|| !pc)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}


	if(NULL==(fp=popen(buf, "r")))
	{
		log_error("%s failure:%s", __func__, strerror);
		return -1;
	}

	
	while(fgets(f_buf, sizeof(f_buf), fp))
	{
		if(strstr(f_buf, "packet"))
		{
			if(strstr(f_buf, "errors,"))
			{
				log_warn("errors, '100/%/' packet loss");
				return -3;
			}	
			else if(ptr=strstr(f_buf, "received,"))
			{
				while(tok=strtok(ptr,", "))//spaces and , 
				{
					if(tok=strtok(NULL,", "))
					{
						if(strstr(tok,"%"));
						{
							ptr=strtok(tok,"%");
							rate=atoi(ptr);
	
							break;
						}
					}
				}

			}

		}
	}
	return 0;

}
 
 
/*********************************************************************************
 *
 *           Name:       route_exist 
 *
 *    Description:       Check whether the PPPD file exists
 *                 
 *        Input args:     
 *                       iface_name:   interface name
 *
 *       Output args: 
 *
 *      return value:
 *                       <0 failure
 *                       =0 success
 *
 *
 *                 
 ********************************************************************************/


int route_exist(char *iface_name)
{

	int     rv=-1;
	char    buf[32];

	if(!iface_name)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}
	memset(buf, 0, sizeof(buf));
	snprintf(buf, sizeof(buf), "/sys/class/net/%s/", iface_name);
	rv=access(buf, F_OK);//success return 0

	return rv;

}
 
 
/*********************************************************************************
 *
 *           Name:         route_get_min_metric 
 *
 *    Description:         Get the minimum metric value  
 *                 
 *        Input args:     
 *
 *       Output args: 
 *                         minimum metric value  
 *
 *      return value:
 *
 *                          <0 failure
 *                          =0 success

 *
 *                 
 ********************************************************************************/



int route_get_min_metric(void)
{
	int     i;
	int     j=0;
	char    f_buf[1024];
	char    r_buf[16];
	FILE   *fp;
	char   *p[16];
	char    ptr_buf[8];
	char   *str;
    char   *min_metric;
	int     min_met[8];
	int     min=-1;

	memset(r_buf, 0, sizeof(r_buf));
	memset(f_buf, 0, sizeof(f_buf));
	memset(min_met, 0, sizeof(min_met));

	if(NULL==(fp=popen("ip route show", "r")))
	{
		log_error("%s failure:%s", __func__, strerror);
		return -1;
	}

	while(fgets(f_buf, sizeof(f_buf), fp))
	{	

//		printf("%s\n", f_buf);
		
		if(strstr(f_buf, "metric"))
		{
			strtok(f_buf," ");//spces
			for(i=0; i<(sizeof(p)/sizeof(p[0])),j<8; i++)
			{
				p[i]=strtok(NULL," ");
		
//				printf("%s\n" ,p[i]);
				if(strstr(p[i],"metric"))
				{
					min_metric=strstr(p[i], "metric");
					min_metric+=strlen("metric")+1;
					min_met[j]=atoi(min_metric);

//					printf(" min_met[%d]:%d\n", j, min_met[j]);
					p[i]=NULL;
					j++;
					break;
				}

			}
		}

	}
	min=min_met[0];
	for(i=0; i<j; i++)
	{
		if(min_met[i]<min)
		{
			min=min_met[i];
		}

	}
//	printf("min:%d\n", min);

	return min;

}
 
 
/*********************************************************************************
 *
 *           Name:      route_add
 *
 *    Description:      Adding a Default  interface
 *                 
 *        Input args:     
 *                       iface_name:   interface name
 *                           metric:   min mertic
 *       Output args: 
 *
 *      return value:
 *
 *                          <0 failure
 *                          =0 success


 *                 
 ********************************************************************************/


int route_add(char *iface_name, int metric)
{
	char       buf[32];

	memset(buf, 0, sizeof(buf));
	if(!iface_name|| (metric<0))
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}


	snprintf(buf, sizeof(buf), "sudo route add default dev %s metric %d", iface_name, metric);

	system(buf);

	return 0;
}
 
 
/*********************************************************************************
 *
 *           Name:          route_del 
 *
 *    Description:          Deleting a Default  interface

 *                 
 *        Input args:     
 *                       iface_name:   interface name
 *                           metric:   min mertic
 *
 *       Output args: 
 *
 *      return value:
 *
 *                          <0 failure
 *                          =0 success


 *                 
 ********************************************************************************/


int route_del(char *iface_name, int metric)
{
	char       buf[32];

	memset(buf, 0, sizeof(buf));
	if(!iface_name|| (metric<0))
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}


	snprintf(buf, sizeof(buf), "sudo route del default dev %s metric %d", iface_name, metric);

	system(buf);

	return 0;
}
 
 
/*********************************************************************************
 *
 *           Name:         route_kill_process 
 *
 *    Description:         Get the pid Kill the process
 *                 
 *        Input args:      
 *                         process_name: process Name
 *
 *       Output args: 
 *
 *      return value:
 *
 *                          <0 failure
 *                          =0 success


 *                 
 ********************************************************************************/


int route_kill_process(char *process_name)
{
	char       buf[64]={0};
	FILE      *fp;
	char       f_buf[8]={0};
	char       kill_buf[32]={0};

	memset(buf, 0, sizeof(buf));
	if(!process_name)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}
/* Reports the current system process status |seek process_name| The first field in a line (a record) delimited by a space is printed.
*/
	snprintf(buf, sizeof(buf), "ps -C %s | grep %s | awk \'{print $1}\'", process_name, process_name);

//	printf("buf:%s\n", buf);
	if(NULL==(fp=popen(buf, "r")))
	{
		log_error("%s failure:%s", __func__, strerror);
		return -1;
	}
/*get pid*/
	fgets(f_buf, sizeof(f_buf), fp);

//	printf("buf:%s\n", f_buf);
	/*kill -15 is better than kill -9*/
	snprintf(kill_buf, sizeof(kill_buf), "sudo kill -15 %s", f_buf);
//	printf("kill:%s\n", kill_buf);

	system(kill_buf);
	log_info("kill process successfully!\n");

	return 0;
}

